package net.sea.setup.ui.wizard.impl;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import net.sea.commons.constants.AppConstants;
import net.sea.commons.context.AppContext;
import net.sea.commons.util.JAXBUtils;
import net.sea.setup.config.Module;
import net.sea.setup.config.ModuleNode;
import net.sea.setup.config.custom.CustomConfig;
import net.sea.setup.ui.wizard.AbstractWizardPage;
import net.sea.setup.ui.wizard.impl.module.CheckNode;
import net.sea.setup.ui.wizard.impl.module.CheckRenderer;

public class ModulePage extends AbstractWizardPage {

	private static final long serialVersionUID = 1L;

	// 向导配置信息对象
	private static Module module = new Module();

	private Map<String, Boolean> isSelectedMap = new HashMap<String, Boolean>();

	// 所有的组件
	private Map<String, ModuleNode> modules = new HashMap<String, ModuleNode>();

	JTree tree;

	public ModulePage() {

		/** 读取组件列表 */
		List<ModuleNode> moduleNodes = getModuleNodes();

		// 组件排序
		sortModule(moduleNodes);

		/** 父节点子节点连接 */
		CheckNode[] nodes = connectNode(moduleNodes);

		/** 树组件环境创建 */
		createContent(nodes);
	}

	/**
	 * 组件排序
	 * 
	 * @param moduleNodes
	 *            组件列表
	 */
	private void sortModule(List<ModuleNode> moduleNodes) {
		Collections.sort(moduleNodes, new ModuleComparator());
	}

	/**
	 * 父节点子节点连接
	 * 
	 * @param moduleNodes
	 * @param nodes
	 */
	private CheckNode[] connectNode(List<ModuleNode> moduleNodes) {
		CheckNode[] nodes = new CheckNode[moduleNodes.size()];
		for (int i = 0; i < moduleNodes.size(); i++) {
			ModuleNode module = moduleNodes.get(i);
			nodes[i] = new CheckNode(module.getModuleName());
			String nodeId = module.getId();
			nodes[i].setId(nodeId);
			nodes[i].setModuleNode(module);
			modules.put(nodeId, module);
			if (!"".equals(module.getModuleParent())) {
				nodes[Integer.valueOf(module.getModuleParent())].add(nodes[i]);
			}
		}
		return nodes;
	}

	/**
	 * 树组件环境创建
	 * 
	 * @param nodes
	 */
	private void createContent(CheckNode[] nodes) {
		tree = new JTree(nodes[0]);
		tree.setCellRenderer(new CheckRenderer());
		tree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.addMouseListener(new NodeSelectionListener(tree));
		expandTree(tree);

		setOpaque(false);
		setBorder("选择安装组件");
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[] { 450, 0, 0 };
		gridBagLayout.rowHeights = new int[] { 10, 0, 0 };
		gridBagLayout.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
		gridBagLayout.rowWeights = new double[] { 1.0, 0.0, Double.MIN_VALUE };
		setLayout(gridBagLayout);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBorder(null);
		GridBagConstraints gbc_scrollPane = new GridBagConstraints();
		gbc_scrollPane.insets = new Insets(0, 0, 5, 5);
		gbc_scrollPane.fill = GridBagConstraints.BOTH;
		gbc_scrollPane.gridx = 0;
		gbc_scrollPane.gridy = 0;
		scrollPane.setViewportView(tree);
		add(scrollPane, gbc_scrollPane);
	}

	/**
	 * 读取组件列表
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<ModuleNode> getModuleNodes() {
		// 获取文件数据
		Map<String, String> dataMap = (Map<String, String>) contextInst
				.getAttribute(AppConstants.DATA_FILE);
		String dataFile = "";
		if (dataMap != null) {
			dataFile = dataMap.get(this.getClass().getName());
		}

		module = (Module) (JAXBUtils.xmlToBean(ModulePage.class
				.getClassLoader().getResourceAsStream(dataFile), Module.class));
		if (module == null) {
			throw new RuntimeException("系统配置错误，请检查。");
		}

		if (null == module.getModuleNodes()) {
			throw new RuntimeException("系统配置信息有误,无可安装组件！");
		}

		return module.getModuleNodes();
	}

	/**
	 * 树展开
	 * 
	 * @param tree
	 */
	public static void expandTree(JTree tree) {
		CheckNode root = (CheckNode) tree.getModel().getRoot();
		expandAll(tree, new TreePath(root), true);
	}

	private static void expandAll(JTree tree, TreePath parent, boolean expand) {
		// Traverse children
		CheckNode node = (CheckNode) parent.getLastPathComponent();
		if (node.getChildCount() >= 0) {
			for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
				CheckNode n = (CheckNode) e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				expandAll(tree, path, expand);
			}
		}

		if (expand) {
			tree.expandPath(parent);
		} else {
			tree.collapsePath(parent);
		}
	}

	/**
	 * 
	 * 组件比较器
	 *
	 * @author huachengwu 
	 */
	private class ModuleComparator implements Comparator<ModuleNode> {
		@Override
		public int compare(ModuleNode beforeModule, ModuleNode afterModule) {
			return beforeModule.getIndex().compareTo(afterModule.getIndex());
		}
	}

	/**
	 * 树事件类
	 * 
	 * @author li_zhen
	 *
	 */
	class NodeSelectionListener extends MouseAdapter {
		JTree tree;

		NodeSelectionListener(JTree tree) {
			this.tree = tree;
		}

		public void mouseClicked(MouseEvent e) {
			// 得到被选的节点
			int x = e.getX();
			int y = e.getY();
			int row = tree.getRowForLocation(x, y);
			TreePath path = tree.getPathForRow(row);
			// 判断是否单击了节点
			if (path != null) {
				// 取得被单击的节点
				CheckNode node = (CheckNode) path.getLastPathComponent();
				boolean isSelected = !(node.isSelected());
				// 设置被单击的节点CheckBox,使其状态与原来状态相反
				node.setSelected(isSelected);
				String nodeId = node.getId();
				isSelectedMap.put(nodeId, isSelected);
				// 如果节点是被选中,则展开子节点
				if (isSelected) {
					tree.expandPath(path);
					// tree.collapsePath(path);
				}
				// 如果被选节点不是叶节点,将其所有子节点设置为CheckBox状态设成与其相同的状态
				if (!node.isLeaf()) {
					node.getNextNode();
					Enumeration<?> enu = node.children();
					while (enu.hasMoreElements()) {
						CheckNode n = (CheckNode) enu.nextElement();
						n.setSelected(node.isSelected());
						isSelectedMap.remove(nodeId);
						isSelectedMap.put(n.getId(), node.isSelected());
						if (!n.isLeaf()) {
							Enumeration<?> enuc = n.children();
							while (enuc.hasMoreElements()) {
								CheckNode c = (CheckNode) enuc.nextElement();
								c.setSelected(node.isSelected());
								isSelectedMap.remove(n.getId());
								isSelectedMap.put(c.getId(), node.isSelected());
							}
						}
					}
				}
				// 刷新树(这步是必须的,否则将看不到上面所有设置的效果);
				((DefaultTreeModel) tree.getModel()).nodeChanged(node);
				tree.revalidate();
				tree.repaint();
			}
		}
	}

	/**
	 * 下一页前校验
	 */
	@Override
	public PageResult validateInput() {
		if (isSelectedMap.containsValue(true)) {
			List<ModuleNode> selectedModules = new ArrayList<ModuleNode>();
			List<String> moduleIds = new ArrayList<String>();
			Set<String> set = isSelectedMap.keySet();
			for (Iterator<String> it = set.iterator(); it.hasNext();) {
				String id = (String) it.next();
				if (isSelectedMap.get(id)) {
					moduleIds.add(id);
					selectedModules.add(modules.get(id));
				}
			}
			sortModule(selectedModules);
			AppContext appContext = AppContext.getInstance();
			appContext.setAttribute(AppConstants.MODULE_LIST, moduleIds);
			appContext.setAttribute(AppConstants.SELECTED_MODULES,
					selectedModules);
			return new PageResult(true);
		}
		return new PageResult(false, "请选择要安装的组件");
	}

	/**
	 * 创建自定义配置
	 */
	@Override
	protected List<CustomConfig> createCustomConfig() {
		return null;
	}
}